home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Deutsche Edition 1
/
Deutsche Edition 1.iso
/
amok
/
021-030
/
amok21
/
hotkey
/
hotkey.mod
< prev
next >
Wrap
Text File
|
1993-11-04
|
7KB
|
212 lines
(*---------------------------------------------------------------------------
:Program. HotKey.mod
:Contents. Simple Installation eines Input-Handlers und einer
:Contents. 'heißen' Taste, also Support für Hintergrundprogramme.
:Author. Bernd Preusing
:Address. Gerhardstr. 16 D-2200 Elmshorn
:Phone. 04121/22486
:Copyright. Public Domain
:Language. Modula-2
:Translator. M2Amiga V3.2e
:History. V1.0 Preusing 01-Apr-89 (kein Scherz!)
:Bugs. nicht reentrant
:Remark. Power to the Bauer!
---------------------------------------------------------------------------*)
IMPLEMENTATION MODULE HotKey;
FROM SYSTEM IMPORT ADR, ADDRESS, LONGSET, CAST, INLINE;
FROM Arts IMPORT CurrentLevel, Terminate, TermProcedure, Assert;
FROM Exec IMPORT Interrupt, IOStdReqPtr, MemReqs, MemReqSet,
Message, MessagePtr, MsgPortPtr,
AllocMem, CloseDevice, DoIO, FindPort, FreeMem,
GetMsg, OpenDevice, PutMsg, WaitPort;
FROM ExecSupport IMPORT CreatePort, DeletePort, CreateStdIO, DeleteStdIO;
FROM Input IMPORT inputName, addHandler, remHandler, writeEvent;
FROM InputEvent IMPORT Class, Qualifiers, QualifierSet, InputEventPtr;
CONST
MemType = MemReqSet{public, memClear}; (* spart Tipparbeit *)
(* Diese Qualifier werden beim Vergleich nicht berücksichtigt: *)
UnusedSet = QualifierSet{multiBroadcast, capsLock, relativeMouse};
STOPYOU = 1234H; (* magic, irgendwas Spezielles *)
ISHOT = 478AH; (* dito *)
A0 = 8+0; A1 = 8+1; (* Register *)
TYPE
CodeRecPtr = POINTER TO CodeRec;
CodeRec = RECORD
code: CARDINAL;
qualifier: QualifierSet
END;
VAR
StartLevel: INTEGER;
ActionPort, (* 2 Ports, sonst gibt es Message-Salat (probiert!) *)
DevicePort: MsgPortPtr;
DeviceIO: IOStdReqPtr;
HotKeyIntr: Interrupt;
HotKey: CodeRec;
AddedHandler: BOOLEAN;
(* vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv *)
(* Input-Handler: (liegt in der Kette vor Intuition) *)
(* $S- *)
(* Verbiete Stackprüfung, wir sind hier in einem fremden Task. *)
(* Andere Laufzeitfehler führen zum Guru. *)
(* Register A0 zeigt auf die InputEvents, A1 auf meine Daten, *)
(* in D0 gebe ich zurück, was ich nicht verarbeiten kann oder will *)
(* Forbid(), Disable() usw. sind völlig überflüssig! *)
PROCEDURE InputHandler(events{A0}: InputEventPtr;
keys{A1} : CodeRecPtr
): InputEventPtr;
VAR OldEvents: InputEventPtr;
Msg : MessagePtr;
BEGIN
(* $Z- Option: Systemparameter gleich in die Register *)
(* Alle Register auf den Stack, A4 und A5 übernimmt der Compiler *)
INLINE(48E7H,0011111100110010L); (* MOVEM.L D2-D7,A2-A3/A6,-(A7) *)
OldEvents:=events;
WHILE events # NIL DO (* WITH wäre hier Unsinn! *)
IF (events^.class = rawkey) AND (events^.code = keys^.code)
AND ((events^.qualifier-UnusedSet) = keys^.qualifier) THEN
events^.class:=null; (* einfach ungültig machen *)
Msg:=AllocMem(SIZE(Message),MemType);
IF Msg # NIL THEN
Msg^.length:=ISHOT;
PutMsg(ActionPort,Msg);
END;
END;
events:=events^.nextEvent;
END;
(* Gerettete Register wiederherstellen *)
INLINE(4CDFH,0100110011111100L); (* MOVEM.L (A7)+,D2-D7,A2-A3/A6 *)
RETURN OldEvents
END InputHandler;
(* $S= $Z= *)
(* alte Stackprüfung wiederherstellen *)
(* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ *)
PROCEDURE AddEvents(events: InputEventPtr);
VAR Next: InputEventPtr;
BEGIN
WHILE events # NIL DO
Next:=events^.nextEvent;
WITH DeviceIO^ DO
command:=writeEvent;
data:=events; (* events^.next wird vom device gelöscht! *)
END;
DoIO(DeviceIO); (* immer ok *)
events:=Next;
END;
END AddEvents;
PROCEDURE InstallHandler(VAR Intr: Interrupt; install:BOOLEAN);
BEGIN
WITH DeviceIO^ DO
IF install THEN
command:=addHandler
ELSE
command:=remHandler
END;
data:=ADR(Intr);
length:=SIZE(Intr);
END;
DoIO(DeviceIO); (* immer ok *)
END InstallHandler;
PROCEDURE InstallKey(Key:CARDINAL; QSet:QualifierSet; KeyProc:PROC;
PortName:ADDRESS);
VAR
OldPort: MsgPortPtr;
MyMsg: MessagePtr;
Value: CARDINAL;
BEGIN
OldPort:=FindPort(PortName);
IF OldPort # NIL THEN (* ist schon da, also alles beenden *)
MyMsg:=AllocMem(SIZE(Message),MemType);
Assert(MyMsg#NIL,ADR("can't create Message"));
MyMsg^.length:=STOPYOU;
PutMsg(OldPort,MyMsg); (* FreeMem macht der andere! *)
Terminate(CurrentLevel()); (* das war's dann. *)
ELSE
ActionPort:=CreatePort(PortName,0);
Assert(ActionPort#NIL,ADR("can't create ActionPort!"));
WITH HotKeyIntr DO
node.pri:=51; (* intuition = 50 *)
data:=ADR(HotKey);
code:=ADR(InputHandler);
END;
HotKey.code:=Key;
HotKey.qualifier:=QSet-UnusedSet;
LOOP (* Endlose Warteschleife *)
InstallHandler(HotKeyIntr, TRUE); (* Handler einschalten *)
AddedHandler:=TRUE;
WaitPort(ActionPort);
MyMsg:=GetMsg(ActionPort);
InstallHandler(HotKeyIntr, FALSE); (* Handler besser ausschalten *)
AddedHandler:=FALSE;
Value:=MyMsg^.length;
FreeMem(MyMsg,SIZE(Message));
IF Value = ISHOT THEN
KeyProc() (* un nu komms Du *)
ELSIF Value = STOPYOU THEN
Terminate(CurrentLevel()) (* aus und vorbei! *)
ELSE
Assert(FALSE,ADR('HotKey: got illegal message'))
END;
END; (* LOOP *)
END;
END InstallKey;
PROCEDURE OpenInput():BOOLEAN;
BEGIN
DevicePort:=CreatePort(NIL,0);
IF DevicePort = NIL THEN RETURN FALSE END;
DeviceIO:=CreateStdIO(DevicePort);
IF DeviceIO = NIL THEN RETURN FALSE END;
OpenDevice(ADR(inputName),0,DeviceIO,LONGSET{});
RETURN DeviceIO^.error = 0
END OpenInput;
PROCEDURE Cleanup; (* TermProcedure *)
VAR Msg: MessagePtr;
BEGIN
IF CurrentLevel() <= StartLevel THEN
IF AddedHandler THEN
InstallHandler(HotKeyIntr, FALSE);
AddedHandler:=FALSE;
END;
IF DeviceIO # NIL THEN
IF CAST(LONGINT,DeviceIO^.unit) > 0 THEN
(* nicht NIL, nicht -1 *)
CloseDevice(DeviceIO)
END;
DeleteStdIO(DeviceIO); DeviceIO:=NIL
END;
IF DevicePort # NIL THEN
DeletePort(DevicePort); DevicePort:=NIL
END;
IF ActionPort # NIL THEN
LOOP (* Port leeren *)
Msg:=GetMsg(ActionPort);
IF Msg=NIL THEN EXIT END;
FreeMem(Msg,SIZE(Message));
END;
DeletePort(ActionPort); ActionPort:=NIL
END;
END
END Cleanup;
BEGIN (* HotKey.mod *)
DevicePort:=NIL;
ActionPort:=NIL;
DeviceIO:=NIL;
AddedHandler:=FALSE;
StartLevel:=CurrentLevel();
TermProcedure(Cleanup);
Assert(OpenInput(),ADR("can't open input.device"));
END HotKey.mod